package com.qianclass.talklive.app.im;

import com.qianclass.talklive.app.utils.Constant;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;


public class IMEgine extends Thread
{
	private Socket client;
	private DataOutputStream dout;
	private DataParser parserData = null;


	public AgencyManager agency_manger = new AgencyManager();
	public GroupManager  group_manager = new GroupManager();
	public LogFile log           = new LogFile();

	// 当前登录用户的注册信息
	public int login_user_id = 0;
	public String login_user_name = null;
	public int login_user_type = 0;
	public String login_user_key = null;

	public int group_id = 0; // 当前用户加入的组id
	public String group_title = null; 	// 当前用户加入的组名称

	private IMEgineEvent __event = null;
//	public  long last_msec = 0;	// 上次的毫秒值

	private String server_ip = Constant.getBaseDynamicIp();
	private int    server_port = 5080;
	private int recon_interval = 0;
	private byte[] byteRead = new byte[1024];
	private int userid;

	public IMEgine(IMEgineEvent event )
	{
		__event = event;
		parserData = new DataParser(this,event);
		init();
		StartTimer(this);
	}

	public boolean init()
	{
		try
		{
			client = new Socket(server_ip,server_port);
			dout = new DataOutputStream(client.getOutputStream());
			//if(log.CreateLogFile())
			{
				this.start();
				parserData.start();
			}
			//else
			//{
			//	__event.OnError(ConstantDefination.ERR_CREATE_LOG_FILE);
			//	return false;
			//}
		}
		catch(Exception e)
		{
			__event.OnConnectionError(ConstantDefination.ERR_INVALID);
			return false;
		}
		return true;
	}

	public void reconnecting()
	{
		try
		{
			Thread.sleep(recon_interval * 1000);
			try
			{
				if( 0 == recon_interval )
				{
					recon_interval = 1;
				}
				recon_interval *= 2;

				client = new Socket(server_ip,server_port);
				dout = new DataOutputStream(client.getOutputStream());
				recon_interval = 0;
				if(login_user_id > 0)
				{// 重新注册
					int ret = register(login_user_id, login_user_name, login_user_type, login_user_key);
					if( 0 == ret )
					{
						if( group_id > 0 )
						{// 将用户加入组
							//12_16先随意加一个group_id
							JoinGroup(group_id, group_title,group_id);
						}
					}
				}
			}
			catch(Exception e)
			{
				__event.OnConnectionError(ConstantDefination.ERR_RECONNECTION);
			}
		}
		catch (InterruptedException e1)
		{
		}
	}

	public void run()
	{
		int nRead = 0;
		try
		{
			DataInputStream socketIn = null;
			socketIn = new DataInputStream(new BufferedInputStream(client.getInputStream()));


			while(true)
			{
				nRead = socketIn.read(byteRead,0, 1024);
				if(nRead > 1)
				{
					parserData.AddData(byteRead,nRead);
				}
			}
		}
		catch(IOException e)
		{
			if(!client.isClosed())
			{
				try
				{
					client.close();
				}
				catch (IOException e1)
				{
					e1.printStackTrace();
				}
			}
			reconnecting();
			run();
		}
	}

	public int register(int uid, String name, int type, String key)
	{
		// 写日志
		String dump = "sdk: register(" + Integer.toString(uid) + "," + name + Integer.toString(type) + "," + key + ")";
		log.WriteLine(dump);
		//

		if( uid < 0 )
		{
			return ConstantDefination.ERR_PARAM;
		}
		login_user_id = uid;
		login_user_name = name;
		login_user_type = type;
		login_user_key = key;

		int nPakLen = 0;
		int nPayload = 0;
		// 构造报文体
		OutPacket out = new OutPacket();
		out.push_back(uid);
		out.push_back(name);
		out.push_back(type);
		out.push_back(key);
		out.push_back("Android SDK 1.6");

		nPayload = out.nPayloadLen;
		nPakLen = PacketHead.headLen + nPayload;
		// 构造报文头
		PacketHead head = new PacketHead(nPakLen,++Packet.packet_id,ConstantDefination.IM_COMMAND_REGISTER,nPayload,0,uid,0,0);
		// 由报文头和报文体构造完整报文
		Packet pak = new Packet( head, out );
		try
		{
			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			//__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}

		return 0;
	}

	public int RegisterForce( int uid, String name, int type, String key )
	{
		// 写日志
		String dump = "sdk: RegisterForce(" + Integer.toString(uid) + "," + name + Integer.toString(type) + "," + key + ")";
		log.WriteLine(dump);
		//
		if( uid < 0 )
		{
			return ConstantDefination.ERR_PARAM;
		}
		login_user_id = uid;
		login_user_name = name;

		int nPakLen = 0;
		int nPayload = 0;
		try
		{
			// 构造报文体
			OutPacket out = new OutPacket();
			out.push_back(uid);
			out.push_back(name);
			out.push_back(type);
			out.push_back(key);
			out.push_back("Android SDK 1.6");

			nPayload = out.nPayloadLen;
			nPakLen = PacketHead.headLen + nPayload;
			// 构造报文头
			PacketHead head = new PacketHead(nPakLen,++Packet.packet_id,ConstantDefination.IM_COMMAND_REGISTERFORCE,nPayload,0,uid,0,0);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet( head, out );

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}
		return 0;
	}

	public int UnRegister()
	{
		// 写日志
		String dump = "sdk: UnRegister()";
		log.WriteLine(dump);
		//
		try
		{
			// 构造一个空报文体
			OutPacket out = new OutPacket();
			// 构造报文头
			PacketHead head = new PacketHead(PacketHead.headLen, 0, ConstantDefination.IM_COMMAND_UNREGISTER, 0, 0, login_user_id, 0, 0);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet(head, out);

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}
		return 0;
	}

	public int FetchAgInfo()
	{
		// 写日志
		String dump = "sdk: FetchAgInfo()";
		log.WriteLine(dump);
		//
		try
		{
			// 构造一个空报文体
			OutPacket out = new OutPacket();
			// 构造报文头
			PacketHead head = new PacketHead(PacketHead.headLen, 0, ConstantDefination.IM_COMMAND_FETCHAGINFO, 0, 0, login_user_id, 0, 0);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet(head, out);

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}
		return 0;
	}

	public int JoinGroup(int gid, String title,int userid)
	{
		// 写日志
		String dump = "sdk: JoinGroup(" + Integer.toString(gid) + "," + title + ")";
		log.WriteLine(dump);
		//
		if( gid <= 0 )
		{
			return ConstantDefination.ERR_PARAM;
		}

		group_id = gid;
		group_title = title;

		int nPakLen = 0;
		int nPayload = 0;
		try
		{
			// 构造报文体
			OutPacket out = new OutPacket();
			out.push_back(gid);
			out.push_back(title);

			nPayload = out.nPayloadLen;
			nPakLen = PacketHead.headLen + nPayload;
			// 构造报文头
			//先判断userid是不是为0，如果是则使用服务器返回来的新userid
			if(login_user_id==0){
				System.out.print("userid是不是为0，如果是则使用服务器返回来的新userid");
				login_user_id=userid;
			}
			PacketHead head = new PacketHead(nPakLen,++Packet.packet_id,ConstantDefination.IM_COMMAND_JOINGROUP,nPayload,0,login_user_id,0,0);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet( head, out );

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			//__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}
		return 0;
	}

	public int LeaveGroup(String group_account)
	{
		// 写日志
		String dump = "sdk: LeaveGroup(" + group_account + ")";
		log.WriteLine(dump);
		//
		int nPakLen = 0;
		int nPayload = 0;
		try
		{
			Integer gid = group_manager.GetGroupId(group_account);
			// 构造报文体
			OutPacket out = new OutPacket();
			out.push_back(gid);

			nPayload = out.nPayloadLen;
			nPakLen = PacketHead.headLen + nPayload;
			// 构造报文头
			PacketHead head = new PacketHead(nPakLen,++Packet.packet_id,ConstantDefination.IM_COMMAND_LEAVEGROUP,nPayload,0,login_user_id,0,0);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet( head, out );

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}

		return 0;
	}

	public int SendMessage( String account, String data)
	{
		// 写日志
		String dump = "sdk: SendMessage(" + account + "," + data + ")";
		log.WriteLine(dump);
		//
		int nPakLen = 0;
		int nPayload = 0;
		int e_type = ConstantDefination.RESULT_SUCCESS;
		try
		{
			e_type = ConstantDefination.ERR_PARAM;

			int pos = account.indexOf(':');
			String str_id = account.substring(0, pos);
			int to_id = Integer.parseInt(str_id);
			int agency_id = agency_manger.GetAgencyIdByIdentify(account);
			// 构造报文体
			OutPacket out = new OutPacket();
			out.push_user_data(data);

			nPayload = out.nPayloadLen;
			nPakLen = PacketHead.headLen + nPayload;

			// 构造报文头
			PacketHead head = new PacketHead(nPakLen,++Packet.packet_id,ConstantDefination.IM_COMMAND_MESSAGE,nPayload,0,login_user_id,to_id,agency_id);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet( head, out );

			e_type = ConstantDefination.ERR_NET_RW;

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			__event.OnError(e_type);
			return e_type;
		}
		return 0;
	}

	public int SendGroupMessage(int msgType, String gCode, String data)
	{
		// 写日志
		String dump = "sdk: SendGroupMessage(" + gCode + "," + data + ")";
		log.WriteLine(dump);
		//
		int nPakLen = 0;
		int nPayload = 0;

		try
		{
			int gid = group_manager.GetGroupId(gCode);
			int agent_id = agency_manger.GetAgencyIdByIdentify(gCode);
			// 构造报文体
			OutPacket out = new OutPacket();
			out.push_user_data(data);

			nPayload = out.nPayloadLen;
			nPakLen = PacketHead.headLen + nPayload;


			// 构造报文头
			PacketHead head = new PacketHead(nPakLen,++Packet.packet_id,ConstantDefination.IM_COMMAND_GMESSAGE,nPayload, msgType,login_user_id,gid,agent_id);
			// 由报文头和报文体构造完整报文
			Packet pak = new Packet( head, out );

			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			__event.OnError(ConstantDefination.ERR_NET_RW);
			return ConstantDefination.ERR_NET_RW;
		}
		return 0;
	}

	/*锁定账号*/
	public int lockUserAccount(int uid, int type)
	{
		// 写日志
		String dump = "sdk: lockUserAccount(" + Integer.toString(uid) + ", type:" + Integer.toString(type);
		log.WriteLine(dump);

		if( uid < 0 )
		{
			return ConstantDefination.ERR_PARAM;
		}

		int nPakLen = 0;
		int nPayload = 0;
		// 构造报文体
		OutPacket out = new OutPacket();
		out.push_back(uid);
		out.push_back(type);

		nPayload = out.nPayloadLen;
		nPakLen = PacketHead.headLen + nPayload;
		// 构造报文头
		PacketHead head = new PacketHead(nPakLen, ++Packet.packet_id,
										 ConstantDefination.IM_COMMAND_LOCKUSER, nPayload,0, uid, 0, 0);
		// 由报文头和报文体构造完整报文
		Packet pak = new Packet(head, out );
		try
		{
			dout.write(pak.data, 0, pak.len);
			dout.flush();
		}
		catch (Exception e)
		{
			return ConstantDefination.ERR_EXCEPTION;
		}

		return 0;
	}

	public  void StartTimer(final IMEgine egine)
	{
		final Timer timer = new Timer();
		timer.schedule(new TimerTask()
		{
			public void run()
			{
				if(egine.login_user_id <= 0)
				{
					return;
				}

				long cur_msec = System.currentTimeMillis();
				if(cur_msec - parserData.last_msec > 15 * 1000 )
				{
					egine.__event.OnLostConnection(ConstantDefination.ERR_ACK_TIMEOUT);
				}
				else
				{
					// 构造一个空报文体
					OutPacket out = new OutPacket();
					// 构造报文头
					PacketHead head = new PacketHead(PacketHead.headLen,++Packet.packet_id, ConstantDefination.IM_COMMAND_ACK,0,0,egine.login_user_id,0,0);
					// 由报文头和报文体构造完整报文
					Packet pak = new Packet( head, out );
					try
					{
						egine.dout.write(pak.data, 0, pak.len);
						egine.dout.flush();
					}
					catch (Exception e)
					{
						// 写日志
						String dump = "timer: sending heartbeat packet error!";
						egine.log.WriteLine(dump);
						//
						egine.__event.OnError(ConstantDefination.ERR_NET_RW);
					}
				}
			}
		}, 0, 5000);
	}
}
